home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / sozobon2.zoo / hcc / gunk.c < prev    next >
C/C++ Source or Header  |  1990-12-14  |  16KB  |  942 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gunk.c
  12.  *
  13.  *    Transformations on expression trees
  14.  *    Most of this stuff is because we cant handle
  15.  *    floats, long mul/div, or fields directly.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "flags.h"
  23. #include "nodes.h"
  24. #include "gen.h"
  25.  
  26. NODEP copyone();
  27.  
  28. #define gwiden(x)    ((x)==1 ? 2 : (x))
  29. #define isfield(np)    ((np)->g_token == '.' && (np)->g_fldw)
  30.  
  31. NODEP npar1, npar2, npar3;
  32. char *spar1, *spar2, *spar3;
  33. int ipar1, ipar2, ipar3;
  34.  
  35. struct rule {
  36.     int (*match)();        /* test for transformation needed */
  37.     int (*rewri)();        /* rewrite function */
  38. };
  39.  
  40. int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
  41. int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
  42. int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
  43.  
  44. struct rule gunktbl[] = {
  45.     {m_unfold, unfold},
  46.     {m_cast, cast},
  47.     {m_md_shf, md_shf},
  48.     {m_eident, eident},
  49.     {m_incdec, incdec},
  50.     {m_hardas, hardas},
  51.     {m_inline, inline}, /* must cast before inline */
  52.     {m_fcmp, fcmp},
  53.     {m_fldas, fldas},
  54.     {0}
  55. };
  56.  
  57. int anygunk;
  58.  
  59. gunk(np)
  60. NODEP np;
  61. {
  62.     do {
  63.         anygunk = 0;
  64.         gunks(np);
  65.     } while (anygunk);
  66. }
  67.  
  68. gunks(np)
  69. register NODEP np;
  70. {
  71.     switch (np->g_type) {
  72.     case E_BIN:
  73.         gunks(np->n_right);
  74.     case E_UNARY:
  75.         gunks(np->n_left);
  76.     }
  77.     gunk1(np);
  78. }
  79.  
  80. gunk1(np)
  81. NODEP np;
  82. {
  83.     register struct rule *p;
  84.  
  85.     for (p=gunktbl; p->match; p++)
  86.         if ((*p->match)(np)) {
  87.             anygunk++;
  88.             (*p->rewri)(np);
  89.             return;
  90.         }
  91. }
  92.  
  93. /*
  94.  *    Change pointer arithmetic to equivalent trees
  95.  *        (main thing is to mult or div by object size)
  96.  */
  97. m_unfold(np)
  98. NODEP np;
  99. {
  100.     switch (np->g_token) {
  101.     case PTRADD:
  102.         ipar1 = '+';
  103.         return 1;
  104.     case PTRSUB:
  105.         ipar1 = '-';
  106.         return 1;
  107.     case PTRDIFF:
  108.         ipar1 = 0;
  109.         return 1;
  110.     case ASSIGN PTRADD:
  111.         ipar1 = ASSIGN '+';
  112.         return 1;
  113.     case ASSIGN PTRSUB:
  114.         ipar1 = ASSIGN '-';
  115.         return 1;
  116.     }
  117.     return 0;
  118. }
  119.  
  120. unfold(np)
  121. NODEP np;
  122. {
  123.     if (ipar1) {
  124.         ins_mul(np, np->g_offs);
  125.         np->g_token = ipar1;
  126.     } else {
  127.         ins_div(np, np->g_offs);
  128.     }
  129. }
  130.  
  131. NODEP
  132. newgcon(kon, ty, sz)
  133. long kon;
  134. {
  135.     register NODEP kp;
  136.  
  137.     kp = allocnode();
  138.     kp->g_token = ICON;
  139.     sprintf(kp->n_name, "%ld", kon);
  140.     kp->g_offs = kon;
  141.     kp->g_type = E_LEAF;
  142.     kp->g_ty = ty;
  143.     kp->g_sz = sz;
  144.     return kp;
  145. }
  146.  
  147. ins_mul(np, kon)
  148. NODEP np;
  149. long kon;
  150. {
  151.     NODEP rp = np->n_right;
  152.     register NODEP mp, kp;
  153.  
  154.     if (kon == 1)
  155.         return;
  156.     if (rp->g_token == ICON) {
  157.         rp->g_offs *= kon;
  158.         rp->g_sz = gwiden(rp->g_sz);
  159.         return;
  160.     }
  161.  
  162.     mp = allocnode();
  163.     mp->g_token = '*';
  164.     sprintf(mp->n_name, "p*");
  165.     mp->g_type = E_BIN;
  166.     mp->g_ty = rp->g_ty;
  167.     mp->g_sz = gwiden(rp->g_sz);
  168.  
  169.     kp = newgcon(kon, mp->g_ty, mp->g_sz);
  170.  
  171.     mp->n_right = kp;
  172.     mp->n_left = np->n_right;
  173.     np->n_right = mp;
  174. }
  175.  
  176. ins_div(np, kon)
  177. register NODEP np;
  178. long kon;
  179. {
  180.     register NODEP tp, kp;
  181.  
  182.     kp = newgcon(kon, np->g_ty, np->g_sz);
  183.  
  184.     tp = copyone(np);
  185.     tp->g_token = '-';
  186.     tp->n_left = np->n_left;
  187.     tp->n_right = np->n_right;
  188.     tp->g_sz = SIZE_P;
  189.     tp->g_ty = ET_U;
  190.  
  191.     np->n_left = tp;
  192.     np->n_right = kp;
  193.     np->g_type = E_BIN;
  194.     np->g_token = '/';
  195.     sprintf(np->n_name, "p/");
  196. }
  197.  
  198. #define CAST_LN    1
  199. #define CAST_RN 2
  200. #define CAST_LLONG    3
  201.  
  202. /*
  203.  *    Insert needed (implied) casts
  204.  */
  205. m_cast(np)
  206. NODEP np;
  207. {
  208.     NODEP lp = np->n_left;
  209.  
  210.     switch (np->g_type) {
  211.     case E_LEAF:
  212.         return 0;
  213.     case E_BIN:
  214.         return bm_cast(np);
  215.     }
  216.     /* must be unary */
  217.     switch (np->g_token) {
  218.     case UNARY '-':
  219.     case '~':
  220.         return castup(lp, np, CAST_LN);
  221.     case TCONV:
  222.         return fcastlong(np);
  223.     }
  224.     return 0;
  225. }
  226.  
  227. bm_cast(np)
  228. register NODEP np;
  229. {
  230.     NODEP lp = np->n_left, rp = np->n_right;
  231.  
  232.     if (isassign(np->g_token)) {
  233.         if (castup(rp, lp, CAST_RN))
  234.             return 1;
  235.         if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
  236.             return 1;
  237.         return 0;
  238.     }
  239.  
  240.     switch (np->g_token) {
  241.     case '=':
  242.         if (np->g_ty == ET_A)
  243.             return 0;
  244.         return castany(rp, lp, CAST_RN);
  245.  
  246.     case '<':
  247.     case '>':
  248.     case DOUBLE '=':
  249.     case NOTEQ:
  250.     case LTEQ:
  251.     case GTEQ:
  252.         if (castup(lp, rp, CAST_LN))
  253.             return 1;
  254.         return castup(rp, lp, CAST_RN);
  255.  
  256.     case '(':
  257.     case ',':
  258.     case '?':
  259.     case DOUBLE '&':
  260.     case DOUBLE '|':
  261.         return 0;
  262.  
  263.     case DOUBLE '<':
  264.     case DOUBLE '>':
  265.         if (castup(lp, np, CAST_LN))
  266.             return 1;
  267.         return castany(rp, np, CAST_RN);
  268.  
  269.     default:
  270.         if (castup(lp, np, CAST_LN))
  271.             return 1;
  272.         return castup(rp, np, CAST_RN);
  273.     }
  274.     return 0;
  275. }
  276.  
  277. fcastlong(np)
  278. NODEP np;
  279. {
  280.     NODEP lp = np->n_left;
  281.  
  282.     if (red_con(lp))
  283.         return 0;
  284.     if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
  285.         ipar1 = CAST_LLONG;
  286.         return 1;
  287.     }
  288.     if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
  289.         ipar1 = CAST_LLONG;
  290.         return 1;
  291.     }
  292.     return 0;
  293. }
  294.  
  295. castup(lowp, hip, par)
  296. NODEP lowp, hip;
  297. {
  298.     if (stronger(hip, lowp)) {
  299.         ipar1 = par;
  300.         npar1 = hip;
  301.         return 1;
  302.     }
  303.     return 0;
  304. }
  305.  
  306. castmagic(p1, p2, par, tok)
  307. NODEP p1, p2;
  308. {
  309.     if (xstronger(p1,p2) && magicop(tok)) {
  310.         ipar1 = par;
  311.         npar1 = p2;
  312.         return 1;
  313.     }
  314.     return 0;
  315. }
  316.  
  317. castany(p1, p2, par)
  318. NODEP p1, p2;
  319. {
  320.     if (p1->g_sz != p2->g_sz ||
  321.         ((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
  322.         ipar1 = par;
  323.         npar1 = p2;
  324.         return 1;
  325.     }
  326.     return 0;
  327. }
  328.  
  329. cast(np)
  330. NODEP np;
  331. {
  332.     switch (ipar1) {
  333.     case CAST_LN:
  334.         castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
  335.         break;
  336.     case CAST_RN:
  337.         castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
  338.         break;
  339.     case CAST_LLONG:
  340.         castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
  341.         break;
  342.     }
  343. }
  344.  
  345. castsub(ty, sz, npp, np)
  346. NODEP *npp, np;
  347. {
  348.     register NODEP tp;
  349.  
  350.     /* ICON cast optimization */
  351.     if (np->g_token == ICON &&
  352.         np->g_ty == ty &&
  353.         np->g_sz < sz) {
  354.         np->g_sz = sz;
  355.         return;
  356.     }
  357.  
  358.     tp = allocnode();
  359.     tp->g_token = TCONV;
  360.     strcpy(tp->n_name, "cast up");
  361.     tp->n_left = np;
  362.     *npp = tp;
  363.     tp->g_sz = sz;
  364.     tp->g_ty = ty;
  365.     tp->g_type = E_UNARY;
  366. }
  367.  
  368. /*
  369.  *    Change stuff computer cant do to calls to inline functions
  370.  *    (in this case, all floats and long *%/)
  371.  */
  372. m_inline(np)
  373. NODEP np;
  374. {
  375.     int isfloat, isuns;
  376.  
  377.     if (np->g_type == E_LEAF)
  378.         return 0;
  379.  
  380.     if (np->g_ty == ET_A)
  381.         return 0;
  382.     isfloat = (np->g_ty == ET_F);
  383.     isuns = (np->g_ty == ET_U);
  384.  
  385.     if (np->g_type == E_UNARY) {
  386.         switch (np->g_token) {
  387.         case UNARY '-':
  388.             if (!isfloat) return 0;
  389.             spar1 = "%fpneg";
  390.             return 1;
  391.         case TCONV:
  392.             if ((np->n_left->g_ty == ET_F) == isfloat)
  393.                 return 0;
  394.             if (red_con(np->n_left))
  395.                 return 0;
  396.             spar1 = isfloat ? "fpltof" : "fpftol";
  397.             return 1;
  398.         }
  399.         return 0;
  400.     }
  401.  
  402.     if (np->g_sz != 4)    /* longs or floats only */
  403.         return 0;
  404.  
  405.     switch (np->g_token) {
  406.     case '*':
  407.         spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
  408.         return 1;
  409.     case '/':
  410.         spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
  411.         return 1;
  412.     case '+':
  413.         if (!isfloat) return 0;
  414.         spar1 = "%fpadd";
  415.         return 1;
  416.     case '-':
  417.         if (!isfloat) return 0;
  418.         spar1 = "%fpsub";
  419.         return 1;
  420.     case '%':
  421.         spar1 = isuns ? "%lremu" : "%lrem";
  422.         return 1;
  423.     }
  424.     return 0;
  425. }
  426.  
  427. inline(np)
  428. NODEP np;
  429. {
  430.     register NODEP nmp, cmap;
  431.     int isunary;
  432.  
  433.     isunary = (np->g_type == E_UNARY);
  434.  
  435.     if (isunary) {
  436.         np->n_right = np->n_left;
  437.         np->g_type = E_BIN;
  438.     } else {
  439.         cmap = copyone(np);
  440.         cmap->n_left = np->n_left;
  441.         cmap->n_right = np->n_right;
  442.         np->n_right = cmap;
  443.  
  444.         cmap->g_token = ',';
  445.         cmap->g_offs = 2;
  446.         strcpy(cmap->n_name, ",inl");
  447.     }
  448.  
  449.     nmp = allocnode();
  450.     np->n_left = nmp;
  451.  
  452.     np->g_token = '(';
  453.     strcpy(np->n_name, "inline");
  454.  
  455.     nmp->g_token = ID;
  456.     strcpy(nmp->n_name, spar1);
  457. #ifdef OUT_AZ
  458.     strcat(nmp->n_name, "